package models

import (
	"github.com/gin-gonic/gin"
	"gorm.io/gorm"
	"time"
	"zong-go/pkg/config"
	"zong-go/pkg/database"
	"zong-go/pkg/logger"
	"zong-go/pkg/pagination"
	"zong-go/pkg/password"
)

// User 用户模型
type User struct {
	BaseModel

	Username string `gorm:"index;column:username;type:varchar(50);not null;unique;"`
	Name     string `gorm:"column:name;type:varchar(50);not null;"`
	Phone    string `gorm:"column:phone;type:varchar(11);not null;"`
	Password string `gorm:"column:password;type:varchar(100);not null;"`
	Avatar   string `gorm:"column:avatar;type:text;"`
	Sex      *int   `gorm:"column:sex;type:tinyint(1);default:1;"`
	Status   *int   `gorm:"column:status;type:tinyint(1);not null;default:1;"`

	// gorm:"-" —— 设置 GORM 在读写时略过此字段，仅用于表单验证
	PasswordComfirm string `gorm:"-"`
}

type ApiUser struct {
	ID        uint64    `gorm:"column:id;"`
	Username  string    `gorm:"column:username;"`
	Name      string    `gorm:"column:name;"`
	Phone     string    `gorm:"column:phone;"`
	Avatar    string    `gorm:"column:avatar;"`
	Sex       *int      `gorm:"column:sex;"`
	Status    *int      `gorm:"column:status;"`
	CreatedAt time.Time `gorm:"column:created_at;"`
}

// Create 创建用户，通过 User.ID 来判断是否创建成功
func (UserModel *User) Create() (err error) {
	if err = database.DB.Model(UserModel).Create(&UserModel).Error; err != nil {
		logger.LogError(err)
		return err
	}

	return nil
}

// Update 更新用户
func (UserModel *User) Update() (err error) {
	if err = database.DB.Model(UserModel).Save(&UserModel).Error; err != nil {
		logger.LogError(err)
		return err
	}

	return nil
}

// Delete 删除用户
func (UserModel *User) Delete() (err error) {
	if err = database.DB.Model(UserModel).Delete(&UserModel).Error; err != nil {
		logger.LogError(err)
		return err
	}

	return nil
}

// GetAllPaging 获取所有用户(分页)
func (UserModel User) GetAllPaging(context *gin.Context, cond map[string]interface{}) (pagination.PaginationObject, error) {
	conditions, values, err := UserModel.WhereBuild(cond)
	if err != nil {
		return pagination.PaginationObject{}, err
	}
	db := database.DB.Model(UserModel)
	if len(values) > 0 {
		db = db.Where(conditions, values...)
	}

	var apiUser []ApiUser

	return pagination.Pagination(context, db, &apiUser, 0)
}

// Get 通过 ID 获取用户
func (UserModel User) Get(id uint64) (ApiUser, error) {
	var apiUser ApiUser
	if err := database.DB.Model(UserModel).First(&apiUser, id).Error; err != nil {
		return apiUser, err
	} else {
		return apiUser, nil
	}
}

// GetAll 获取所有用户
func (UserModel User) GetAll() ([]ApiUser, error) {
	db := database.DB.Model(UserModel)

	if UserModel.Username != "" {
		db = db.Where("username = ?", UserModel.Username)
	}

	var apiUser []ApiUser
	if err := db.Find(&apiUser).Error; err != nil {
		return apiUser, err
	}

	return apiUser, nil
}

// GetByID 通过 id 来获取用户
func (UserModel User) GetByID(id uint64) (User, error) {
	if err := database.DB.Model(UserModel).First(&UserModel, id).Error; err != nil {
		return UserModel, err
	} else {
		return UserModel, nil
	}
}

// GetByUsername 通过 username 来获取用户
func (UserModel User) GetByUsername(username string) (User, error) {
	if err := database.DB.Model(UserModel).Where("username = ?", username).First(&UserModel).Error; err != nil || err == gorm.ErrRecordNotFound {
		return UserModel, err
	} else {
		return UserModel, nil
	}
}

// ResetPassword 重置密码
func (UserModel *User) ResetPassword(password string) (err error) {
	UserModel.Password = password
	if err = database.DB.Model(UserModel).Save(&UserModel).Error; err != nil {
		logger.LogError(err)
		return err
	}

	return nil
}

// ComparePassword 对比密码是否匹配
func (UserModel User) ComparePassword(_password string) bool {
	return password.CheckHash(_password, UserModel.Password)
}

// anotherSql 另外的数据库连接池
func anotherSql() *gorm.DB {
	adb := database.MysqlConnector(database.ConnData{
		Connection: config.Get("database", "connection"),
		Host:       config.Get("database", "host"),
		Port:       config.Get("database", "port"),
		Database:   config.Get("database", "database"),
		Username:   config.Get("database", "username"),
		Password:   config.Get("database", "password"),
		Charset:    config.Get("database", "charset"),
	})

	return adb
}
